#include "Driver_GPTIM.h"

static void Driver_GPTIM_SetDutyCycle(GPTIM_Type *gptimX, uint32_t channel, uint8_t dutyCycle);
static void Driver_GPTIM_DisableAllChannel(void);

static GPIOConfig gptimGPIOConfigList[] = {
    [GPTIM_GPIO_INDEX_AM1]     = { GPIOA,
                                   { FL_GPIO_PIN_4, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                     FL_ENABLE, FL_DISABLE } },
    [GPTIM_GPIO_INDEX_AM2]     = { GPIOA,
                                   { FL_GPIO_PIN_5, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                     FL_ENABLE, FL_DISABLE } },
    [GPTIM_GPIO_INDEX_AM5]     = { GPIOB,
                                   { FL_GPIO_PIN_10, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                     FL_ENABLE, FL_DISABLE } },
    [GPTIM_GPIO_INDEX_AM6]     = { GPIOB,
                                   { FL_GPIO_PIN_11, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                     FL_ENABLE, FL_DISABLE } },
    [GPTIM_GPIO_INDEX_AM7]     = { GPIOC,
                                   { FL_GPIO_PIN_0, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                     FL_DISABLE, FL_DISABLE } },
    [GPTIM_GPIO_INDEX_AM8]     = { GPIOC,
                                   { FL_GPIO_PIN_1, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                     FL_DISABLE, FL_DISABLE } },
    [GPTIM_GPIO_INDEX_PUMP_EN] = { GPIOC,
                                   { FL_GPIO_PIN_11, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL,
                                     FL_DISABLE, FL_ENABLE, FL_DISABLE } },
};

/**
 * @brief 初始化通用定时器
 *
 */
void Driver_GPTIM_Init(void)
{
    FL_GPTIM_InitTypeDef    gptimInit   = { 0 };
    FL_GPTIM_OC_InitTypeDef gptimOCInit = { 0 };

    for (uint8_t i = 0; i < GPTIM_GPIO_INDEX_MAX; ++i) {
        FL_GPIO_Init(gptimGPIOConfigList[i].port, &(gptimGPIOConfigList[i].gpioInit));
    }

    /* GPTIM通用初始化 */
    gptimInit.prescaler       = 32 - 1;                     /* 分频系数 */
    gptimInit.counterMode     = FL_GPTIM_COUNTER_DIR_UP;    /* 向上计数 */
    gptimInit.autoReload      = 100 - 1;                    /* 自动重装载值100 */
    gptimInit.clockDivision   = FL_GPTIM_CLK_DIVISION_DIV1; /* 死区和滤波分频 */
    gptimInit.autoReloadState = FL_ENABLE;                  /* 预装载preload使能 */
    FL_GPTIM_Init(GPTIM0, &gptimInit);
    FL_GPTIM_Init(GPTIM1, &gptimInit);

    gptimOCInit.OCMode       = FL_GPTIM_OC_MODE_PWM1;       /* 输出比较模式PWM1 */
    gptimOCInit.OCETRFStatus = FL_DISABLE;                  /* OC1REF不受ETR影响 */
    gptimOCInit.OCFastMode   = FL_DISABLE;                  /* 关闭快速使能 */
    gptimOCInit.compareValue = 50;                          /* 比较值0 */
    gptimOCInit.OCPolarity   = FL_GPTIM_OC_POLARITY_NORMAL; /* OC正常输出 */
    gptimOCInit.OCPreload    = FL_DISABLE;                  /* OC preload 无效 */

    // GPTIM0
    FL_GPTIM_OC_Init(GPTIM0, FL_GPTIM_CHANNEL_1, &gptimOCInit); /* AM5_EN PWM */
    FL_GPTIM_OC_Init(GPTIM0, FL_GPTIM_CHANNEL_2, &gptimOCInit); /* AM6_EN PWM */
    FL_GPTIM_OC_Init(GPTIM0, FL_GPTIM_CHANNEL_3, &gptimOCInit); /* PUMP_EN PWM */

    // GPTIM1
    FL_GPTIM_OC_Init(GPTIM1, FL_GPTIM_CHANNEL_1, &gptimOCInit); /* AM7_EN PWM */
    FL_GPTIM_OC_Init(GPTIM1, FL_GPTIM_CHANNEL_2, &gptimOCInit); /* AM8_EN PWM */
    FL_GPTIM_OC_Init(GPTIM1, FL_GPTIM_CHANNEL_3, &gptimOCInit); /* AM1_EN PWM */
    FL_GPTIM_OC_Init(GPTIM1, FL_GPTIM_CHANNEL_4, &gptimOCInit); /* AM2_EN PWM */

    FL_GPTIM_Enable(GPTIM0);                                    /* 使能定时器 */
    FL_GPTIM_Enable(GPTIM1);                                    /* 使能定时器 */

    /* 泵不参与缓升缓降，直接100%占空比 */
    FL_GPTIM_WriteCompareCH3(GPTIM0, 100);

    Driver_GPTIM_DisableAllChannel();
}

/**
 * @brief 按照设定的占空比 使能或禁用 选择的通道
 *
 * @param gptimX            定时器号
 * @param channel           通道号
 * @param isComplementary   是否为互补通道
 * @param dutyCycle         占空比
 * @param isEnable          使能 or 禁用
 */
void Driver_GPTIM_SetChannelDutyAndState(void *gptimX, uint32_t channel, bool isComplementary,
                                         uint8_t dutyCycle, bool isEnable)
{
    Driver_GPTIM_SetDutyCycle(gptimX, channel, dutyCycle);

    if (isEnable) {
        FL_GPTIM_OC_EnableChannel(gptimX, channel);
    }
    else {
        FL_GPTIM_OC_DisableChannel(gptimX, channel);
    }
}

/**
 * @brief 设置占空比
 *
 * @param gptimX        定时器号
 * @param channel       通道号
 * @param dutyCycle     占空比
 */
static void Driver_GPTIM_SetDutyCycle(GPTIM_Type *gptimX, uint32_t channel, uint8_t dutyCycle)
{
    if (dutyCycle > FULL_DUTY_CYCLE) {
        dutyCycle = FULL_DUTY_CYCLE / 2;
    }

    switch (channel) {
    case FL_GPTIM_CHANNEL_1: FL_GPTIM_WriteCompareCH1(gptimX, dutyCycle); break;
    case FL_GPTIM_CHANNEL_2: FL_GPTIM_WriteCompareCH2(gptimX, dutyCycle); break;
    case FL_GPTIM_CHANNEL_3: FL_GPTIM_WriteCompareCH3(gptimX, dutyCycle); break;
    case FL_GPTIM_CHANNEL_4: FL_GPTIM_WriteCompareCH4(gptimX, dutyCycle); break;
    default:                 LOG("Driver_GPTIM_SetDutyCycle(): channel error!\n"); break;
    }
}

/**
 * @brief 禁用所有的通道
 *
 */
static void Driver_GPTIM_DisableAllChannel(void)
{
    Driver_GPTIM_SetChannelDutyAndState(GPTIM0, FL_GPTIM_CHANNEL_1, false, 0, false);
    Driver_GPTIM_SetChannelDutyAndState(GPTIM0, FL_GPTIM_CHANNEL_2, false, 0, false);
    // Driver_GPTIM_SetChannelDutyAndState(GPTIM0, FL_GPTIM_CHANNEL_3, false, 0, false);
    // Driver_GPTIM_SetChannelDutyAndState(GPTIM0, FL_GPTIM_CHANNEL_4, false, 0, false);
    Driver_GPTIM_SetChannelDutyAndState(GPTIM1, FL_GPTIM_CHANNEL_1, false, 0, false);
    Driver_GPTIM_SetChannelDutyAndState(GPTIM1, FL_GPTIM_CHANNEL_2, false, 0, false);
    Driver_GPTIM_SetChannelDutyAndState(GPTIM1, FL_GPTIM_CHANNEL_3, false, 0, false);
    Driver_GPTIM_SetChannelDutyAndState(GPTIM1, FL_GPTIM_CHANNEL_4, false, 0, false);
}
